local nn_rule                        = require "niuniu.nn_rule"
local error_code                     = require "error_code"
local constant                       = require "constant"
local table_def                      = require "table_def"
local game_def                      = require "game_def"
local cards_common                   = require "cards"
local table_insert                   = table.insert
local table_sort                     = table.sort
local table_remove                   = table.remove
local math_floor                     = math.floor
local table_unpack                   = table.unpack
local math_random                    = math.random
local string_format 				 = string.format
local math_abs                       = math.abs

local MAX_SIDE_NUM                   = 5
local BANKER_SIDE_NUM                = MAX_SIDE_NUM

local GAME_STATUS_INIT               = 0    --初始化状态
local GAME_STATUS_START              = 1    --游戏开始
local GAME_STATUS_BET                = 2    --押注
local GAME_STATUS_OVER               = 3    --结束状态

local MT_INDEX                       = {}
local M                              = {}

local AVAILABLE_SIDES_MAP            = {
    [1] = true,
    [2] = true,
    [3] = true,
    [4] = true
}

M.AVAILABLE_SIDES_MAP                = AVAILABLE_SIDES_MAP
M.MAX_SIDE_NUM                       = MAX_SIDE_NUM

M.RICH_SEAT_SIDE                     = 3      --富豪No.1座位
M.LUCK_SEAT_SIDE                     = 4      --运气王座位

--math.randomseed(os.time())


local function copy_table(t)
    local new_t = {}

    for k,v in pairs(t) do
        new_t[k] = v
    end

    return new_t
end

function MT_INDEX:shuffle(swap_times)
    assert(self.game_status == GAME_STATUS_START)

    local cards = self.cards
    local card_count = #cards
    swap_times = card_count or swap_times

    for i = 1, swap_times do
        local n = math_random(1, card_count)
        local m = math_random(1, card_count)

        if n ~= m then
            cards[n], cards[m] = cards[m], cards[n]
        end
    end
end

function MT_INDEX:start_game()
    assert(self.game_status == GAME_STATUS_INIT)

    self.game_status = GAME_STATUS_START
end

local function find_best_card_set(self,side_cards_map)
    local side_has_best_cards
    for side,cards in pairs(side_cards_map) do
        if side_has_best_cards then
            local src_tile_list = side_cards_map[side]
            local dst_tile_list = side_cards_map[side_has_best_cards]
            local src_type = nn_rule.get_card_type(src_tile_list,self.sorted_special_card_type)
            local dst_type = nn_rule.get_card_type(dst_tile_list,self.sorted_special_card_type)

            if nn_rule.compare_card(src_type,src_tile_list,dst_type,dst_tile_list) then
                side_has_best_cards = side
            end
        else
            side_has_best_cards = side
        end
    end

    return side_has_best_cards
end

--把self.sort_side_cards_map中牌由大到小对应的座位号存到record_cards_sort
function MT_INDEX:get_sort_cards()
    local record_cards_sort = {}   --根据牌的大小(由大到小)记录座位号
    local result
    local compare_times = MAX_SIDE_NUM - 1
    for side,record in pairs(self.sort_side_cards_map) do
        table_insert(record_cards_sort,side)
    end
    local sort_side_cards_map = {}
    for side,record in pairs(self.sort_side_cards_map) do
        table_insert(sort_side_cards_map,record)
    end
    for i = 1,compare_times do   
        local temp = MAX_SIDE_NUM - i

        for j = 1,temp do
            local side_cards1 = sort_side_cards_map[j]
            local side_cards2 = sort_side_cards_map[j+1]
            local side_card_type1 = nn_rule.get_card_type(side_cards1, self.sorted_special_card_type)
            local side_card_type2 = nn_rule.get_card_type(side_cards2, self.sorted_special_card_type)
            local side_bet_result
            result = nn_rule.compare_card(side_card_type1, side_cards1, side_card_type2, side_cards2)
            if not result then
                record_cards_sort[j],record_cards_sort[j+1] = record_cards_sort[j+1],record_cards_sort[j]
                sort_side_cards_map[j],sort_side_cards_map[j+1] = sort_side_cards_map[j+1],sort_side_cards_map[j]
            end
        end
    end 
    return record_cards_sort
end

function MT_INDEX:have_used_card(deal_card)
    for side, side_cards in pairs(self.side_cards_map) do
        for k, card in pairs(side_cards) do
            if deal_card == card then
                return true
            end
        end
    end

    return false
end

--更新剩余的牌
function MT_INDEX:update_rest_cards()
    self.rest_cards = copy_table(self.all_cards)
    for i = #self.rest_cards,1,-1 do
        if self:have_used_card(self.rest_cards[i]) then
            table_remove(self.rest_cards,i)
        end 
    end
end

function MT_INDEX:deal()
    assert(self.game_status == GAME_STATUS_START)
    local cards = self.cards
    local side_cards_map = self.side_cards_map
    local sort_side_cards_map = self.sort_side_cards_map

    for k = 1, MAX_SIDE_NUM do
        local card_list = {}
        side_cards_map[k] = card_list        
        for i = 1, constant.NN_MAX_CARDS_COUNT do
            table_insert(card_list, assert(table_remove(cards)))
        end
        -- sort_side_cards_map[k] = copy_table(card_list)
        sort_side_cards_map[k] = card_list
        nn_rule.sort_card_list(sort_side_cards_map[k])
    end
    print("==========MT_INDEX:deal===",cards_common.card_list_to_str_kp(sort_side_cards_map))
    self:update_rest_cards()        --更新剩余的牌
end

function MT_INDEX:get_all_side_tile_list()
    return self.sort_side_cards_map
end

function MT_INDEX:set_max_times()
    for card_type, times in pairs(self.card_type_times_map) do
        if self.max_times < times then
            self.max_times = times
        end
    end
end

function MT_INDEX:init(card_type_times_map, sorted_special_card_type, table_type)
    local make_card_id = nn_rule.make_card_id
    local cards = {}

    for i = 1, 13 do
        for j = 1, 4 do
            table_insert(cards, make_card_id(j, i))
        end
    end

    self.game_status = GAME_STATUS_INIT
    self.cards = cards
    self.rest_cards = {}          --发完牌后剩余的牌
    self.all_cards = cards        --54张牌
    -- self.reduce_award_store = false   --是否从奖金库存拿钱
    self.side_cards_map = {}
    self.sort_side_cards_map = {}
    self.player_bet_map = {}       --当前游戏中的玩家列表
    self.player_coins_data_map = {}
    self.banker_uid = nil
    self.is_robot_banker = true
    self.game_result = {}
    self.game_result.game_valid = false
    self.total_bet_coins = 0       --下注总额
    self.card_type_times_map = card_type_times_map
    self.sorted_special_card_type = sorted_special_card_type
    self.max_times = 0
    self.robot_use_pic_num = 0          --当局使用表情的机器人数
    self.betting_list = {
        [1] = 0,
        [2] = 0,
        [3] = 0,
        [4] = 0,
    }

    self:start_game()
    self:shuffle()
    self:set_max_times()
    
    self.robot_betting_list = {
        [1] = {},
        [2] = {},
        [3] = {},
        [4] = {},
    }
    self.player_list = {}
    return true
end

function MT_INDEX:check_bet_num(player_list,player_not_bet_num)
    local ret5 = {}
    local ret4 = {}
    for uid,info in pairs(player_list) do
        if not self.player_bet_map[uid] and self.banker_uid ~= uid then
            player_not_bet_num[uid] = player_not_bet_num[uid] or 0
            player_not_bet_num[uid] = player_not_bet_num[uid] + 1
            if player_not_bet_num[uid] >= 5 then
                table_insert(ret5,uid)
            end
            if player_not_bet_num[uid] == 4 then
                table_insert(ret4,uid)
            end
        else
            player_not_bet_num[uid] = 0
        end
    end
    for uid,num in pairs(player_not_bet_num) do
        if not player_list[uid] then
            player_not_bet_num[uid] = nil
        end
    end    
    return ret5,ret4
end

function MT_INDEX:had_init_player_coins(uid)
    local player_data = self.player_coins_data_map[uid]

    if player_data then
        return true
    else
        return false
    end
end

function MT_INDEX:init_player_coins(uid, curr_own_coins)
	--warlog("MT_INDEX:init_player_coins", uid, curr_own_coins)

    local player_data = {}

    self.player_coins_data_map[uid] = player_data
    player_data.curr_own_coins = curr_own_coins
    player_data.bet_total_coins = 0
end

function MT_INDEX:update_curr_own_coins(uid, curr_own_coins)
    local player_data = self.player_coins_data_map[uid]
    player_data.curr_own_coins = curr_own_coins
end

function MT_INDEX:set_banker(uid,is_robot)
    self.banker_uid = uid
    self.is_robot_banker = is_robot
end

function MT_INDEX:get_side_robot_type_betting_coins(side,coins_type)
    return self.robot_betting_list[side][coins_type] or 0
end

function MT_INDEX:get_robot_side_bet_list()
    local ret = {}
    for side,info in pairs(self.robot_betting_list) do
        for bet_type,coins in pairs(info) do
            ret[side] = (ret[side] or 0) + coins
        end
    end

    return ret
end

function MT_INDEX:is_available_betting(coins,available_betting_list) --押注金额是否有效
    --local betting_list = constant.LFDJ_AVAILABLE_BET_COINS_LIST
    for i = 1,#available_betting_list do
        if available_betting_list[i] == coins then
            return true
        end
    end

    return false
end

--玩家在本局下注的总额度
function MT_INDEX:get_uid_bet_total(uid)
    local player_data = self.player_coins_data_map[uid]

    if not player_data then
        return 0
    end

    return player_data.bet_total_coins
end

function MT_INDEX:is_side_limit(side,coins,self_table_type) 
    local roomdata = global_configs.roomdata[self_table_type]
    if not roomdata then return false end

    if roomdata.all_spade_limit and roomdata.all_spade_limit ~= 0 and side == 1 and self.betting_list[1] + coins > roomdata.all_spade_limit then
        return true
    end
    if roomdata.all_heart_limit and roomdata.all_heart_limit ~= 0 and side == 2 and self.betting_list[2] + coins > roomdata.all_heart_limit then
        return true
    end
    if roomdata.all_club_limit and roomdata.all_club_limit ~= 0 and side == 3 and self.betting_list[3] + coins > roomdata.all_club_limit then
        return true
    end
    if roomdata.all_diamond_limit and roomdata.all_diamond_limit ~= 0 and side == 4 and self.betting_list[4] + coins > roomdata.all_diamond_limit then
        return true
    end
    return false
end

function MT_INDEX:is_personal_limit(uid,side,coins,self_table_type) 
--    dbglog("self_table_type:",self_table_type)
    local roomdata = global_configs.roomdata[self_table_type]
    if not roomdata or not roomdata.person_limit then return false end

    if roomdata.person_limit[1] and roomdata.person_limit[1] ~= 0 and coins < roomdata.person_limit[1] then 
        return true
    end
    --dbglog("roomdata.person_limit:",roomdata.person_limit[1],roomdata.person_limit[2])
    local all_coins = coins
    local records = self.player_bet_map[uid] or {}
    for side,info in pairs(records) do
        all_coins = all_coins + info.bet_coins
    end
    if roomdata.person_limit[2] and roomdata.person_limit[2] ~= 0 and all_coins > roomdata.person_limit[2] then
        return true
    end
    return false
end

function MT_INDEX:is_personal_side_limit(uid,side,coins,self_table_type) 
--    dbglog("self_table_type:",self_table_type)
    local roomdata = global_configs.roomdata[self_table_type]
    if not roomdata then return false end
    local records = self.player_bet_map[uid] or {}

    if roomdata.spade_limit and roomdata.spade_limit ~= 0 and side == 1 and records[1] and records[1].bet_coins + coins > roomdata.spade_limit then
        return true
    end
    if roomdata.heart_limit and roomdata.heart_limit ~= 0 and side == 2 and records[2] and records[2].bet_coins + coins > roomdata.heart_limit then
        return true
    end
    if roomdata.club_limit and roomdata.club_limit ~= 0 and side == 3 and records[3] and records[3].bet_coins + coins > roomdata.club_limit then
        return true
    end
    if roomdata.diamond_limit and roomdata.diamond_limit ~= 0 and side == 4 and records[4] and records[4].bet_coins + coins > roomdata.diamond_limit then
        return true
    end
    return false
end

function MT_INDEX:can_bet(uid,side,bet_coins,player_info,is_robot,bet_type,table_type)
    if self.game_status ~= GAME_STATUS_BET then
        return false, error_code.NOT_BET_STATUS_ERRROR
    end

    if uid == self.banker_uid then
        return false, error_code.BANKER_CANT_BET_ERROR
    end

    if bet_type ~= constant.BET_TYPE_CONTINUE and not self:is_available_betting(bet_coins,player_info.available_betting_list) then
        return false, error_code.BET_SELECT_NUMBER_ERROR
    end

    if not AVAILABLE_SIDES_MAP[side] then
        return false, error_code.BET_SIDE_ERROR 
    end

    if self:is_side_limit(side,bet_coins,table_type) then --某一边是否到最大了
        return false, error_code.SIDE_BET_LIMIT
    end

    if self:is_personal_side_limit(uid,side,bet_coins,table_type) then --个人某一边是否最大了
        return false, error_code.PERSONAL_SIDE_BET_LIMIT
    end

    if self:is_personal_limit(uid,side,bet_coins,table_type) then --
        return false, error_code.PERSONAL_BET_LIMIT
    end

    if not self:had_init_player_coins(uid) then
        self:init_player_coins(uid, player_info.coins)
    end

    local player_data = self.player_coins_data_map[uid]

    --判断玩家下注是否超过自己赔付的额度
    if (player_data.bet_total_coins + bet_coins) * self.max_times > player_data.curr_own_coins then
        if (game_def.get_game_type(table_type) or 0) == table_def.GAME_TYPE_TEN_BR_NN then
 
            return false,error_code.TEN_BET_COINS_MORE_THAN_SELF_PAY
        end

        return false, error_code.BET_COINS_MORE_THAN_SELF_PAY_ERROR
    end

    --判断玩家下注是否超过庄家赔付的额度
    local banker_data = self.player_coins_data_map[self.banker_uid]

    if constant.SYSTEM_DO_BANKER_UID ~= self.banker_uid then
        if (self.total_bet_coins + bet_coins) * self.max_times > banker_data.curr_own_coins then

            return false, error_code.BET_COINS_MORE_THAN_BANKER_PAY_ERROR
        end
    end
    return true
end

function MT_INDEX:bet(uid,side,bet_coins,player_info,is_robot,bet_type,table_type)
    if self.game_status ~= GAME_STATUS_BET then
        return false, error_code.NOT_BET_STATUS_ERRROR
    end

    if uid == self.banker_uid then
        return false, error_code.BANKER_CANT_BET_ERROR
    end

    if bet_type ~= constant.BET_TYPE_CONTINUE and not self:is_available_betting(bet_coins,player_info.available_betting_list) then
        return false, error_code.BET_SELECT_NUMBER_ERROR
    end

    if not AVAILABLE_SIDES_MAP[side] then
        return false, error_code.BET_SIDE_ERROR 
    end

    if self:is_side_limit(side,bet_coins,table_type) then --某一边是否到最大了
        return false, error_code.SIDE_BET_LIMIT
    end

    if self:is_personal_side_limit(uid,side,bet_coins,table_type) then --个人某一边是否最大了
        return false, error_code.PERSONAL_SIDE_BET_LIMIT
    end

    if self:is_personal_limit(uid,side,bet_coins,table_type) then --
        return false, error_code.PERSONAL_BET_LIMIT
    end

    if not self:had_init_player_coins(uid) then
        self:init_player_coins(uid, player_info.coins)
    end

    local player_data = self.player_coins_data_map[uid]

    --判断玩家下注是否超过自己赔付的额度
    if (player_data.bet_total_coins + bet_coins) * self.max_times > player_data.curr_own_coins then
        if (game_def.get_game_type(table_type) or 0) == table_def.GAME_TYPE_TEN_BR_NN then
 
            return false,error_code.TEN_BET_COINS_MORE_THAN_SELF_PAY
        end

        return false, error_code.BET_COINS_MORE_THAN_SELF_PAY_ERROR
    end

    --判断玩家下注是否超过庄家赔付的额度
    local banker_data = self.player_coins_data_map[self.banker_uid]

    if constant.SYSTEM_DO_BANKER_UID ~= self.banker_uid then
        if (self.total_bet_coins + bet_coins) * self.max_times > banker_data.curr_own_coins then

            return false, error_code.BET_COINS_MORE_THAN_BANKER_PAY_ERROR
        end
    end

    self:update_curr_own_coins(uid, player_info.coins)

    local player_bet_map = self.player_bet_map
    local records = player_bet_map[uid]

    if not records then
        records = {}
        player_bet_map[uid] = records
    end

    local side_bet = records[side] or { bet_coins = 0 }
    records[side] = side_bet

    --设置玩家的下注金额
    side_bet.bet_coins = side_bet.bet_coins + bet_coins
    player_data.bet_total_coins = player_data.bet_total_coins + bet_coins

    if is_robot then
        local coins_type = player_info.coins_type
        self.robot_betting_list[side][coins_type] =  (self.robot_betting_list[side][coins_type] or 0) + bet_coins
    else
        self.player_list[uid] = true
    end

    local side_bet_coins = self.betting_list[side] + bet_coins
    self.betting_list[side] = side_bet_coins
    self.total_bet_coins = self.total_bet_coins + bet_coins
    self.game_result.game_valid = true

    return true, {
        side_bet_coins = side_bet_coins,
        my_side_bet_coins = side_bet.bet_coins,
        curr_coins = player_data.curr_own_coins - player_data.bet_total_coins,
    }
end

function MT_INDEX:start_bet()
    assert(self.game_status == GAME_STATUS_START)

    self.game_status = GAME_STATUS_BET
    return true
end

function MT_INDEX:stop_bet()
     assert(self.game_status == GAME_STATUS_BET)   
    self.game_status = GAME_STATUS_OVER
    return true
end

function MT_INDEX:is_betting()
    return self.game_status == GAME_STATUS_BET
end

function MT_INDEX:is_game_over()
    return self.game_status == GAME_STATUS_OVER
end

function MT_INDEX:get_my_bet_list(uid)
    local player_bet_map = self.player_bet_map
    local records = player_bet_map[uid]

    if not records then
        return
    end
    
    local ret = {}

    for side, info in pairs(records) do
        ret[side] = info.bet_coins
    end
    
    return ret
end

function MT_INDEX:get_my_bet(uid)
    local player_bet_map = self.player_bet_map
    local records = player_bet_map[uid]

    if not records then
        return
    end
    
    local ret = 0

    for side, info in pairs(records) do
        ret = ret + info.bet_coins
    end
    
    return ret
end

function MT_INDEX:get_all_bet_list()
    local ret = {}

    for side, bet_coins in pairs(self.betting_list) do
        ret[side] = bet_coins
    end
    
    return ret
end    

function MT_INDEX:get_side_player_bet_list(side)
    local side_bet_list = {}
    for uid,records in pairs(self.player_bet_map) do
        if records[side] then
            table_insert(side_bet_list,{uid = uid,bet_coins = records[side].bet_coins or 0})
        end
    end

    return side_bet_list
end

function MT_INDEX:get_bet_info(self_game_type)
    --如果是系统坐庄则不显示
    if constant.SYSTEM_DO_BANKER_UID == self.banker_uid then
        return self.total_bet_coins
    end

    local banker_data = self.player_coins_data_map[self.banker_uid]
    local total_bet_limit = math_floor(banker_data.curr_own_coins / 5)
    if self_game_type == table_def.GAME_TYPE_TEN_BR_NN then
        total_bet_limit = math_floor(banker_data.curr_own_coins / 10)
    end
    --print("total_bet_limit====",table_type,total_bet_limit)
    return self.total_bet_coins,total_bet_limit - self.total_bet_coins
end

function MT_INDEX:assembly_tile_info(side, type, times)
    local tile_info = {}

    tile_info.score = self.side_cards_map[side]
    tile_info.side = side
    tile_info.type = type
    tile_info.times = times
    return tile_info
end

function MT_INDEX:get_betting_uid_list()
    local betting_uid_list = {}
    for uid,_ in pairs(self.player_bet_map) do
        table_insert(betting_uid_list,uid)
    end
    return betting_uid_list
end

function MT_INDEX:get_compare_info(tile_list, sides_result_list)
    local banker_cards = self.sort_side_cards_map[BANKER_SIDE_NUM]
    local banker_card_type = nn_rule.get_card_type(banker_cards, self.sorted_special_card_type)
    tile_list[BANKER_SIDE_NUM] = self:assembly_tile_info(BANKER_SIDE_NUM, banker_card_type, 0)
--    print_r(self.sort_side_cards_map)
--    print_r(self.side_cards_map)
    for side, side_cards in pairs(self.sort_side_cards_map) do
        if side ~= BANKER_SIDE_NUM then
            local side_card_type = nn_rule.get_card_type(side_cards, self.sorted_special_card_type)
            local times = 1
            local side_bet_result = {}
 
            sides_result_list[side] = side_bet_result
            side_bet_result.win = nn_rule.compare_card(side_card_type, side_cards, banker_card_type, banker_cards)            
--            print_r(self.card_type_times_map)
            if side_bet_result.win then
                times = self.card_type_times_map[side_card_type]
            else
                times = self.card_type_times_map[banker_card_type]
            end

            side_bet_result.times = times
            tile_list[side] = self:assembly_tile_info(side, side_card_type, times)
        end
    end
end

-- 输赢控制
function MT_INDEX:control_result(robot_manager,self_table_type,lose_limit,sys_win)
    --系统赢的排列列表
    local win_list = {}
    --系统输的排列列表
    local lose_list = {}
    local cards_map = copy_table(self.side_cards_map)
    local sort_cards_map = copy_table(self.sort_side_cards_map)

    local function permute(a,k)
        local len = #a
        if(len == k) then
            local b = {}
            for i,j in pairs(a) do
                b[i] = j
                -- self.side_cards_map[i] = copy_table(cards_map[j])
                -- self.sort_side_cards_map[i] = copy_table(sort_cards_map[j])
                self.side_cards_map[i] = cards_map[j]
                self.sort_side_cards_map[i] = sort_cards_map[j]                
            end
            local result = self:get_system_result(robot_manager,self_table_type)
            dbglog("result:",result)
            if result > 0 then
                table.insert(win_list,{result = result,list = b})
            elseif result < 0 and math_abs(result) < lose_limit then
                table.insert(lose_list,{result = result,list = b})
            end
        else
            for i=k, len do
                a[i], a[k] = a[k], a[i]
                permute(a,k+1)
                a[i], a[k] = a[k], a[i]
            end
        end
    end
    permute({1,2,3,4,5},1)
    --print("brnn control_result lose_limit:",lose_limit," win_list:",#win_list," lose_list:",#lose_list)
    if sys_win == true and #win_list > 0 then 
        for i,j in pairs(win_list[1].list) do
            self.side_cards_map[i] = cards_map[j]
            self.sort_side_cards_map[i] = sort_cards_map[j]
        end
        dbglog("brnn control_result sys win  result:",win_list[1].result)
        return 0
    elseif sys_win == false and #lose_list > 1 then 
        table_sort(lose_list,function(a, b)
            return a.result > b.result
        end)

        for i,j in pairs(lose_list[2].list) do
            self.side_cards_map[i] = cards_map[j]
            self.sort_side_cards_map[i] = sort_cards_map[j]
        end
        dbglog("brnn control_result sys lose  result:",lose_list[2].result)
        return 0
    elseif #win_list > 0 then    --极端情况下没有符合条件的放分结果，则吃分
        for i,j in pairs(win_list[1].list) do
            self.side_cards_map[i] = cards_map[j]
            self.sort_side_cards_map[i] = sort_cards_map[j]
        end
        errlog("brnn control_result error system win sys_win:",sys_win)
        return 1
    end
    errlog("brnn control_result error error error sys_win:",sys_win)
    
    return 2
end

-- 随机发牌
function MT_INDEX:suiji_result(robot_manager,self_table_type,lose_limit)
    --系统胜利的排列列表
    local sys_win_list = {}

    local res = self:get_system_result(robot_manager,self_table_type)
    if res >= 0 or math_abs(res) < lose_limit then
        dbglog("brnn suiji system result:",res)
        return 0
    end
    --系统赢的排列列表
    local win_list = {}
    --系统输的排列列表
    local lose_list = {}
    local cards_map = copy_table(self.side_cards_map)
    local sort_cards_map = copy_table(self.sort_side_cards_map)

    local function permute(a,k)
        local len = #a
        if(len == k) then
            local b = {}
            for i,j in pairs(a) do
                 b[i] = j
                self.side_cards_map[i] = cards_map[j]
                self.sort_side_cards_map[i] = sort_cards_map[j]
            end
            local result = self:get_system_result(robot_manager,self_table_type)
            dbglog("brnn suiji system lose result:",result,"lose_limit:",lose_limit)
            if result < 0 and res < 0 and math_abs(result) < lose_limit then
                dbglog("brnn suiji system lose result:",result)
                return true 
            end
            if result > 0 then
                table.insert(sys_win_list,{result = result,list = b})
            end 
        else
            for i=k, len do
                a[i], a[k] = a[k], a[i]
                if permute(a,k+1) == true then return true end
                a[i], a[k] = a[k], a[i]
            end
        end
        return false
    end
    if permute({1,2,3,4,5},1) == true then return 0 end   
    --没有找到符合原胜负的组合让系统赢
    for i,j in pairs(sys_win_list[1].list) do
        self.side_cards_map[i] = cards_map[j]
        self.sort_side_cards_map[i] = sort_cards_map[j]
    end
    errlog("brnn suiji error sys win!!!! result:",sys_win_list[1].result) 
    return 1
end

-- 个人控制
function MT_INDEX:control_player(robot_manager,self_table_type,lose_limit,uid,player_win)
    --个人赢的排列列表
    local win_list = {}
    --个人输的排列列表
    local lose_list = {}
    --系统胜利的排列列表
    local sys_win_list = {}
    local cards_map = copy_table(self.side_cards_map)
    local sort_cards_map = copy_table(self.sort_side_cards_map)

    local function permute(a,k)
        local len = #a
        if(len == k) then
            local b = {}
            for i,j in pairs(a) do
                 b[i] = j
                self.side_cards_map[i] = cards_map[j]
                self.sort_side_cards_map[i] = sort_cards_map[j]
            end

            local result_player = self:get_control_player_result(self_table_type,uid)
            local result_sys = self:get_system_result(robot_manager,self_table_type)
            
            if result_player > 0 and ( result_sys > 0 or math_abs(result_sys) < lose_limit) then
                table.insert(win_list,{result = result_player,list = b})
            elseif result_player < 0 and ( result_sys > 0 or math_abs(result_sys) < lose_limit) then
                table.insert(lose_list,{result = result_player,list = b})
            end

            if result_sys > 0 then
                table.insert(sys_win_list,{result = result_sys,list = b})
            end 

        else
            for i=k, len do
                a[i], a[k] = a[k], a[i]
                permute(a,k+1)
                a[i], a[k] = a[k], a[i]
            end
        end
    end
    permute({1,2,3,4,5},1)


    if player_win == true and #win_list > 0 then
        for i,j in pairs(win_list[1].list) do
            self.side_cards_map[i] = cards_map[j]
            self.sort_side_cards_map[i] = sort_cards_map[j]
        end
        dbglog("brnn control_player  win  uid:",uid,"  result:",win_list[1].result)
        return 0   
    elseif player_win == false and #lose_list > 0 then
        for i,j in pairs(lose_list[1].list) do
            self.side_cards_map[i] = cards_map[j]
            self.sort_side_cards_map[i] = sort_cards_map[j]
        end
        dbglog("brnn control_player  lose  uid:",uid,"  result:",lose_list[1].result)
        return 0
    else
        --没有找到符合个人控制的组合让系统赢
        for i,j in pairs(sys_win_list[1].list) do
            self.side_cards_map[i] = cards_map[j]
            self.sort_side_cards_map[i] = sort_cards_map[j]
        end
        dbglog("brnn control_player error sys win  uid:",uid,"  result:",sys_win_list[1].result)
        return 1
    end

    return 0
end


--获取系统输赢的结果
function MT_INDEX:get_system_result(robot_manager,self_table_type)
    local tile_list = {}
    local sides_result_list = {}
    local result = 0                 --系统输赢钱
    local roomdata = global_configs.roomdata[self_table_type]
    local fee_percent = (roomdata.cost or 5) / 100
    local robot_type = roomdata.robot_type or "brnn_normal"
    local bet_list = self:get_all_bet(robot_manager)                  --获取每个区域机器人和玩家下注的金额
    --和庄家比较得出比较结果信息
    self:get_compare_info(tile_list, sides_result_list)
    --系统坐庄或者机器人坐庄，判断系统相对于真实玩家赢了多少钱
    if constant.SYSTEM_DO_BANKER_UID == self.banker_uid or robot_manager[self.banker_uid] then
        for side = 1, MAX_SIDE_NUM - 1 do
            local side_bet_result = sides_result_list[side] 
            local time = side_bet_result.times
            local bet_side = bet_list[side]
            if side_bet_result.win then
                result = result - bet_side.player_bet * time
            else
                result = result + bet_side.player_bet * time
            end 
        end     
    else   --玩家坐庄，判断当前下注机器人赢了多少钱
        for side = 1, BANKER_SIDE_NUM - 1 do
            local side_bet_result = sides_result_list[side] 
            local time = side_bet_result.times
            local bet_side = bet_list[side]
            if side_bet_result.win then 
                result = result + bet_side.robot_bet * time 
            else
                result = result - bet_side.robot_bet * time
            end 
        end
    end

    return result
end

--受控玩家四个区域下注金额由大到小排序
function MT_INDEX:get_side_bet_sort(uid)
    local side_sort_list

    local records = self.player_bet_map[uid]
    if records == nil then    --没有任何下注行为
        return side_sort_list
    end

    side_sort_list = {1,2,3,4}         --四个区域
    --随机交换一下，（针对需求：若存在下注相等的，在下注相等的区域随机一个）
    for i = 1, 4 do
        local n = math_random(1,4)
        local m = math_random(1,4)
        if n ~= m then
            side_sort_list[n], side_sort_list[m] = side_sort_list[m], side_sort_list[n]
        end
    end

    local compare_times = BANKER_SIDE_NUM - 2
    for i = 1, compare_times do
        local temp = BANKER_SIDE_NUM - 1 - i
        for j = 1, temp do
            local side_bet1 = records[j] or { bet_coins = 0 }
            local side_bet2 = records[j+1] or { bet_coins = 0 }
            if side_bet1.bet_coins < side_bet2.bet_coins then
                side_sort_list[j], side_sort_list[j+1] = side_sort_list[j+1], side_sort_list[j]
            end
        end
    end

    return side_sort_list
end

--计算控制玩家的输赢情况
function MT_INDEX:get_control_player_result(self_table_type,control_uid)
    local result = 0       --受控玩家输赢钱结果
    local tile_list = {}
    local sides_result_list = {}            
    local roomdata = global_configs.roomdata[self_table_type]
    --和庄家比较得出比较结果信息
    self:get_compare_info(tile_list, sides_result_list)

    --受控玩家坐庄时计算手控玩家相对于机器人和其他玩家的输赢
    if self.banker_uid == control_uid then    
        for side = 1, MAX_SIDE_NUM - 1 do
            local side_bet_result = sides_result_list[side] 
            local time = side_bet_result.times
            if side_bet_result.win then
                result = result - self.betting_list[side] * time
            else
                result = result + self.betting_list[side] * time 
            end 
            dbglog("===========22222self.betting_list[side]",self.betting_list[side])
        end
    else   --受控玩家是闲家
        local records = self.player_bet_map[control_uid]
        if records == nil then    --没有任何下注行为(玩家坐庄除外),不做任何处理，即随机发牌,理论上受控玩家都是从下注玩家中挑选的
            return
        end
        for side = 1, BANKER_SIDE_NUM - 1 do
            local side_bet_result = sides_result_list[side] 
            local time = side_bet_result.times
            local side_bet = records[side] or { bet_coins = 0 }
         
            if side_bet_result.win then
                result = result + side_bet.bet_coins * time
            else
                result = result - side_bet.bet_coins * time
            end
        end
    end

    return result
end

--某副牌是第几大
function MT_INDEX:get_sort_index(side)
    local sort_map = self:get_sort_cards()    --五副牌由大到小的顺序
    for sort_index, card_side in pairs(sort_map) do
        if card_side == side then
            return sort_index
        end
    end
end

function MT_INDEX:get_sort_side(index)
    local sort_map = self:get_sort_cards()    --五副牌由大到小的顺序
    for sort_index,card_side in pairs(sort_map) do
        if sort_index == index then
            return card_side
        end
    end
end

function MT_INDEX:get_power_card_info(index)
    local card_power = {}
    local sort_map = self:get_sort_cards()
    local side = sort_map[index]
    -- local side_card_list = copy_table(self.side_cards_map[side])
    local side_card_list = self.side_cards_map[side]
    local card_type = nn_rule.get_card_type(side_card_list,self.sorted_special_card_type)
    card_power.card_type = card_type
    card_power.cards = side_card_list

    return card_power
end

function MT_INDEX:is_control(index,change_flag,side,control_win,robot_manager,self_table_type,control_uid)
    local is_control
    local card_list
    local cards_power = self:get_power_card_info(index) 
    
    dbglog("================2222222222is_control()",index,change_flag,side)
    if change_flag then    
        card_list = nn_rule.get_cards(self.rest_cards,nil,cards_power,self.sorted_special_card_type)  
    else
        card_list = nn_rule.get_cards(self.rest_cards,cards_power,nil,self.sorted_special_card_type)
    end
    if card_list and #card_list == 5 then
        dbglog("============222222222222control side before",side,tostring_r(self.side_cards_map[side]))
        -- local sort_list = copy_table(card_list)
        local sort_list = card_list
        nn_rule.sort_card_list(sort_list)
        self.side_cards_map[side] = card_list
        self.sort_side_cards_map[side] = sort_list
        self:update_rest_cards()              --更新剩余的牌
        dbglog("============22222221control side after",side,tostring_r(card_list))
    end

    local result = 0
    if robot_manager then         --走系统控制
        result = self:get_system_result(robot_manager,self_table_type)
    else                          --走个人控制
        result = self:get_control_player_result(self_table_type,control_uid)
    end

    if control_win then                  --控制赢
        if result > 0 then        --成功控制了赢
            dbglog("============22222222222cotrol win ok",result)
            is_control = true
        end
    else
        if result < 0 then        --成功控制了输
            dbglog("============22222222222cotrol lose ok",result)
            is_control = true
        end
    end
    dbglog("============111111111111 control result",result,is_control)
    return is_control
end

--函数功能（使庄家输）：系统或机器人坐庄控制系统输（或控制玩家赢），玩家坐庄控制系统赢（或控制玩家输）
--当庄家牌型>=牛五，使庄家牌型变小(例：五副牌由大到小排序，庄家牌是第三大，依次找比排第四小的牌，第五小的牌给庄家，知道庄家输）
--没找到牌，控制失败，做特殊处理，直接让庄家和最小牌交换，庄家输
--当庄家牌型<牛五，使天地玄黄牌大于庄家牌（找大于庄家的牌替换天地玄黄的牌）,没找到牌，控制失败，做特殊处理，直接让庄家和最小牌交换，庄家输
function MT_INDEX:contral_strategy_one(control_win,card_type,robot_type,robot_manager,self_table_type,control_uid)
    local change_flag = false           --使牌变大还是变小，false为变小
    local robot_control = global_configs.robot[robot_type]
    local type = robot_control.card_compare_value or 5
    local change_flag = false           --使牌变大还是变小，false为变小
    dbglog("==================22222222222card_type",card_type)
    if card_type >= type then   --庄家牌型大于等于牛五,改变庄家牌型，使其点数变小
        local index = self:get_sort_index(MAX_SIDE_NUM)  --某副牌是第几大
        local new_index
        while index < 5 do
            change_flag = false
            new_index = index + 1
            if self:is_control(new_index,change_flag,BANKER_SIDE_NUM,control_win,robot_manager,self_table_type,control_uid) then
                break
            else
                dbglog("=============222222222222222222222no control",index)
                index = index + 1
            end
        end   
        --没有找到合适的牌，直接让庄家和最小牌交换
        if index == 5 and self:get_sort_index(MAX_SIDE_NUM) ~= 5 then 
            local sort_map = self:get_sort_cards()
            local side = sort_map[5]
            self.side_cards_map[MAX_SIDE_NUM], self.side_cards_map[side] = self.side_cards_map[side],self.side_cards_map[MAX_SIDE_NUM]
            self.sort_side_cards_map[MAX_SIDE_NUM], self.sort_side_cards_map[side] = self.sort_side_cards_map[side],self.sort_side_cards_map[MAX_SIDE_NUM]
        end
    else                     --庄家牌型小于牛五,改变天地玄黄牌型，使其点数变大
        local side_list = {1,2,3,4}
        local is_control
        for i = 1, 4 do
            local side_index = math_random(1,#side_list)
            local side = table_remove(side_list,side_index)
            local sort_index = self:get_sort_index(side)  --某副牌是第几大
            local banker_sort_index = self:get_sort_index(BANKER_SIDE_NUM)
            if sort_index > banker_sort_index then        --闲家比庄家牌型小，改变闲家牌型使其变大
                change_flag = true                        --change_flag为true表示使牌型变大
                dbglog("============22222222222222contral_strategy_one",side,sort_index,banker_sort_index,i)
                if self:is_control(banker_sort_index,change_flag,side,control_win,robot_manager,self_table_type,control_uid) then
                    is_control = true
                    break
                end
            end
        end
        if not is_control and self:get_sort_index(MAX_SIDE_NUM) ~= 5 then   --没有找到合适的牌，直接让庄家和最小牌交换
            print("=============contral_strategy_one special")
            local sort_map = self:get_sort_cards()
            local side = sort_map[5]
            self.side_cards_map[MAX_SIDE_NUM], self.side_cards_map[side] = self.side_cards_map[side],self.side_cards_map[MAX_SIDE_NUM]
            self.sort_side_cards_map[MAX_SIDE_NUM], self.sort_side_cards_map[side] = self.sort_side_cards_map[side],self.sort_side_cards_map[MAX_SIDE_NUM]
        end
    end
end

--函数功能（使庄家赢）：系统或机器人坐庄时控制系统赢，玩家坐庄时控制系统输
--当庄家牌型>=牛五，使天地玄黄牌小于庄家牌（找小于庄家的牌替换天地玄黄的牌）,没找到牌，控制失败，做特殊处理，直接让庄家和最大牌交换，庄家赢
--当庄家牌型<牛五，使庄家牌型变大(例：五副牌由大到小排序，庄家牌是第四大，依次找比排第三大的牌，第二大，第一大的牌给庄家，知道庄家赢）,
--没找到牌，控制失败，做特殊处理，直接让庄家和最大牌交换，庄家赢
function MT_INDEX:contral_strategy_two(control_win,card_type,robot_type,robot_manager,self_table_type,control_uid,robots_manager)
    local robot_control = global_configs.robot[robot_type]
    local type = robot_control.card_compare_value or 5
    dbglog("contral_strategy_two====11",card_type,type)
    local manager = robot_manager or robots_manager
    if card_type >= type then              --庄家牌型大于等于牛五,改变天地玄黄牌型，使其点数变小
        local in_control = true
        local side_list = {1,2,3,4}
        for _,side in pairs(side_list) do
            if self:is_player_be_on_side(manager,side) then
                local sort_index = self:get_sort_index(side)  --某副牌是第几大
                local banker_sort_index = self:get_sort_index(BANKER_SIDE_NUM)
                print("contral_strategy_two==00",sort_index,banker_sort_index)
                if sort_index < banker_sort_index then         --闲家比庄家大，改变闲家牌型，使其变小
                    dbglog("============222222222222222contral_strategy_two",side,sort_index,banker_sort_index)
                    in_control = false
                    if self:is_control(banker_sort_index,false,side,control_win,robot_manager,self_table_type,control_uid) then --使牌变小
                        in_control = true
                        break
                    end
                end
            end
        end

        if not in_control then--没有找到合适的牌,直接让庄家和最大牌交换
            print("contral_strategy_two==in_control==11")
            local sort_map = self:get_sort_cards()
            local side = sort_map[1]
            self.side_cards_map[MAX_SIDE_NUM], self.side_cards_map[side] = self.side_cards_map[side],self.side_cards_map[MAX_SIDE_NUM]
            self.sort_side_cards_map[MAX_SIDE_NUM], self.sort_side_cards_map[side] = self.sort_side_cards_map[side],self.sort_side_cards_map[MAX_SIDE_NUM]
        end
    else                                                 --庄家牌型小于牛五,改变庄家牌型，使其点数变大
        local index = self:get_sort_index(MAX_SIDE_NUM)  --某副牌是第几大
        print("contral_strategy_two==cc",index)
        local in_control = true
        while index > 1 do
            local new_index = index - 1
            local side = self:get_sort_side(new_index)
            print("contral_strategy_two==zz",new_index,side,self:is_player_be_on_side(manager,side))
            if side and self:is_player_be_on_side(manager,side) then
                in_control = false
                if self:is_control(new_index,true,BANKER_SIDE_NUM,control_win,robot_manager,self_table_type,control_uid) then ---使牌变大
                    in_control = true
                    break  
                end
            end
        
            index = index - 1
        end 

        --没有找到合适的牌,直接让庄家和最大牌交换
        if not in_control then 
            print("contral_strategy_two==in_control==22")
            local sort_map = self:get_sort_cards()
            local side = sort_map[1]
            self.side_cards_map[MAX_SIDE_NUM], self.side_cards_map[side] = self.side_cards_map[side],self.side_cards_map[MAX_SIDE_NUM]
            self.sort_side_cards_map[MAX_SIDE_NUM], self.sort_side_cards_map[side] = self.sort_side_cards_map[side],self.sort_side_cards_map[MAX_SIDE_NUM]
        end 
    end
end

--系统输钱超过限定进行特殊处理
--1.系统或机器人做庄家，不走系统控制（no_control=true）时，当庄家牌型大于牛五，使天地玄黄的牌变小(找比庄家牌小的牌给天地玄黄)，当庄家牌小于牛五，使庄家牌变大
--2.系统或机器人做庄家，走系统控制，让庄家牌型变大（这个地方找的是比庄家当前牌大的牌，忘了为什么，，，）
--3,玩家当庄，不走系统控制时，当庄家牌型大于牛五，使庄家点数变小（找比庄家当前牌小的牌），当庄家牌小于牛五，找比庄家大的牌给天地玄黄
--4,玩家当庄，走系统控制时，使庄家点数变小（找比庄家当前牌小的牌）
--5，找牌不成功，如果玩家当庄，让庄家拿最小牌，系统当庄，让庄家拿最大牌
function MT_INDEX:adjust_cards_again(no_control,robot_type,robot_manager,self_table_type,tmp_lose_limit)
    local change_flag = false           --使牌变大还是变小，false为变小
    local robot_store = global_configs.robot_store[self_table_type]
    local robot_control = global_configs.robot[robot_type]
    local type = robot_control.card_compare_value or 5
    local lose_limit = tmp_lose_limit or 10
    local result = self:get_system_result(robot_manager,self_table_type)  --系统输赢结果
    local banker_cards = self.sort_side_cards_map[BANKER_SIDE_NUM]
    local card_type = nn_rule.get_card_type(banker_cards, self.sorted_special_card_type)
    local times = 0       --循环次数
    local side_list = {1,2,3,4}
    local side = MAX_SIDE_NUM

    while result < 0 and math_abs(result) > lose_limit and times < 10 do
        dbglog("=============11111111math_abs(result)",math_abs(result),lose_limit)
        local card_list
        local index = self:get_sort_index(MAX_SIDE_NUM)  --某副牌是第几大
        local cards_power = self:get_power_card_info(index)
        if constant.SYSTEM_DO_BANKER_UID == self.banker_uid or robot_manager[self.banker_uid] then    
            if no_control then
                if card_type >= type then     --天地玄黄点数变小
                    if #side_list < 1 then
                        break
                    end
                    local side_index = math_random(1,#side_list)
                    side = table_remove(side_list,side_index)
                    index = self:get_sort_index(side)
                    cards_power = self:get_power_card_info(index)
                    card_list = nn_rule.get_cards(self.rest_cards,cards_power,nil,self.sorted_special_card_type)
                else                       --庄家点数变大
                    card_list = nn_rule.get_cards(self.rest_cards,nil,cards_power,self.sorted_special_card_type) 
                end 
            else                           --使庄家点数变大
                card_list = nn_rule.get_cards(self.rest_cards,nil,cards_power,self.sorted_special_card_type)  
            end
        else 
            if no_control then
                if card_type >= type then       --庄家点数变小
                    card_list = nn_rule.get_cards(self.rest_cards,cards_power,nil,self.sorted_special_card_type)
                else                         --天地玄黄点数变大
                    if #side_list < 1 then
                        break
                    end
                    local side_index = math_random(1,#side_list)
                    side = table_remove(side_list,side_index)
                    index = self:get_sort_index(side)
                    cards_power = self:get_power_card_info(index)
                    card_list = nn_rule.get_cards(self.rest_cards,nil,cards_power,self.sorted_special_card_type)
                end 
            else                             --使庄家点数变小
                card_list = nn_rule.get_cards(self.rest_cards,cards_power,nil,self.sorted_special_card_type) 
            end                                                       
        end
        if card_list and #card_list == 5 then
            -- local sort_list = copy_table(card_list)
            local sort_list = card_list
            nn_rule.sort_card_list(sort_list)
            self.side_cards_map[side] = card_list
            self.sort_side_cards_map[side] = sort_list
            self:update_rest_cards()        --更新剩余的牌
            print("=============11111deal_special===",tostring_r(self.sort_side_cards_map)) 
        end

        result = self:get_system_result(robot_manager,self_table_type)
        times = times + 1    
    end
    --循环十次还没控制成功，直接让系统赢
    if times == 10 and result < 0 and math_abs(result) > lose_limit then
        print("============deal special special")
        if constant.SYSTEM_DO_BANKER_UID == self.banker_uid or robot_manager[self.banker_uid] then    --系统或机器人当庄直接让庄家拿最大牌
            local sort_map = self:get_sort_cards()
            local side = sort_map[1]
            self.side_cards_map[MAX_SIDE_NUM], self.side_cards_map[side] = self.side_cards_map[side],self.side_cards_map[MAX_SIDE_NUM]
            self.sort_side_cards_map[MAX_SIDE_NUM], self.sort_side_cards_map[side] = self.sort_side_cards_map[side],self.sort_side_cards_map[MAX_SIDE_NUM]
        else     --玩家当庄，庄家拿最小牌
            local sort_map = self:get_sort_cards()
            local side = sort_map[5]
            self.side_cards_map[MAX_SIDE_NUM], self.side_cards_map[side] = self.side_cards_map[side],self.side_cards_map[MAX_SIDE_NUM]
            self.sort_side_cards_map[MAX_SIDE_NUM], self.sort_side_cards_map[side] = self.sort_side_cards_map[side],self.sort_side_cards_map[MAX_SIDE_NUM]
            print("=============2222deal_special===",tostring_r(self.sort_side_cards_map))
        end
    end
    dbglog("===========1111111111111111111111times",times,side,result)
end

--系统坐庄（或机器人坐庄）控制系统输赢，玩家坐庄控制系统输赢
function MT_INDEX:adjust_cards(control_win,robot_manager,self_table_type,robot_type)
    local banker_cards = self.sort_side_cards_map[BANKER_SIDE_NUM]
    local card_type = nn_rule.get_card_type(banker_cards, self.sorted_special_card_type)

    if constant.SYSTEM_DO_BANKER_UID == self.banker_uid or robot_manager[self.banker_uid] then
        if control_win then          --控制系统赢
            self:contral_strategy_two(control_win,card_type,robot_type,robot_manager,self_table_type)
        else                         --控制系统输
            self:contral_strategy_one(control_win,card_type,robot_type,robot_manager,self_table_type)  
        end 
    else
        if control_win then          --控制系统赢
            self:contral_strategy_one(control_win,card_type,robot_type,robot_manager,self_table_type)
        else                         --控制系统输
            self:contral_strategy_two(control_win,card_type,robot_type,robot_manager,self_table_type)
        end 
    end
end

--是否有玩家下注
function MT_INDEX:is_player_bet(robot_manager)
    local player_bet_total = 0
    local bet_list = self:get_all_bet(robot_manager)
    for side = 1, MAX_SIDE_NUM - 1 do
        local bet_side = bet_list[side]
        player_bet_total = player_bet_total + bet_side.player_bet
    end
    if player_bet_total > 0 then
        return true
    end

    return false
end

function MT_INDEX:is_player_be_on_side(robot_manager,cmp_side)
    if not robot_manager then
        return false
    end

    local bet_list = self:get_all_bet(robot_manager)
    for side = 1, MAX_SIDE_NUM - 1 do
        local bet_side = bet_list[side]
        if side == cmp_side then
            return bet_side.player_bet > 0 
        end
    end

    return false
end

-- --根据库存策略调整牌型
-- function MT_INDEX:adjust_system_cards(system_result,robot_manager,self_table_type,robot_type,banker_is_robot)
--     local result = 0
--     if system_result then
--         --系统当庄时没有玩家下注，不用管调控策略
--         if not self:is_player_bet(robot_manager) and banker_is_robot then    
--             --对系统输钱超过限定进行特殊处理
--             local no_control = true
--             self:deal_special(no_control,robot_type,robot_manager,self_table_type)
--             return
--         end

--         local control_win
--         result = self:get_system_result(robot_manager,self_table_type)  --系统输赢结果
--         dbglog("==============111111adjust_system_cards",system_result,result)
--         if system_result == constant.SYSTEM_STORE_WIN then        --控制系统赢
--             if result <= 0 then
--                 control_win = true
--                 self:set_cards(control_win,robot_manager,self_table_type,robot_type)
--                 return
--             end
--         elseif system_result == constant.SYSTEM_STORE_LOSE then   --控制系统输
--             if result >= 0 then
--                 control_win = false
--                 self:set_cards(control_win,robot_manager,self_table_type,robot_type)
--                 return
--             end
--         elseif system_result == constant.AWARD_STORE_LOSE then    --控制系统输，玩家从奖金库存拿钱
--             self.reduce_award_store = true                    --玩家从奖金库存拿钱
--             if result >= 0 then
--                 control_win = false
--                 dbglog("=======11111111111from_award_store ")
--                 self:set_cards(control_win,robot_manager,self_table_type,robot_type)
--                 return
--             end
--         end 
--         --对系统输钱超过限定进行特殊处理
--         local no_control = true
--         self:deal_special(no_control,robot_type,robot_manager,self_table_type)  
--     end
-- end

--受控玩家作闲家时控制他赢，依次使下注多的区域牌型变大
function MT_INDEX:control_player_win(self_table_type,control_uid,side_sort_list)
    local player_result = self:get_control_player_result(self_table_type,control_uid)
    local sort = 1
    while player_result <= 0 and sort <= 4 do
        local card_list
        local side = side_sort_list[sort]
        local side_index = self:get_sort_index(side)                --某副牌是第几大
        local banker_index = self:get_sort_index(BANKER_SIDE_NUM)         
        if side_index > banker_index then      --天地玄黄比庄家牌型小，使天地玄黄牌型变大
            local cards_power = self:get_power_card_info(banker_index)
            card_list = nn_rule.get_cards(self.rest_cards,nil,cards_power,self.sorted_special_card_type)
        end
        if card_list and #card_list == 5 then
            -- local sort_list = copy_table(card_list)
            local sort_list = card_list
            nn_rule.sort_card_list(sort_list)
            self.side_cards_map[side] = card_list
            self.sort_side_cards_map[side] = sort_list
            self:update_rest_cards()        --更新剩余的牌
            player_result = self:get_control_player_result(self_table_type,control_uid)
            print("=============11111control_player_win===",tostring_r(self.sort_side_cards_map))
        end
        sort = sort + 1
    end

    if player_result <= 0 then      --没有控制成功，则直接使庄家的牌与最小的牌交换
        local sort_map = self:get_sort_cards()    --五副牌由大到小的顺序
        local min_side = sort_map[5]
        if min_side ~= BANKER_SIDE_NUM then
            self.side_cards_map[min_side], self.side_cards_map[BANKER_SIDE_NUM] = self.side_cards_map[BANKER_SIDE_NUM], self.side_cards_map[min_side]
            self.sort_side_cards_map[min_side], self.sort_side_cards_map[BANKER_SIDE_NUM] = self.sort_side_cards_map[BANKER_SIDE_NUM], self.sort_side_cards_map[min_side]
        end
        print("=============22222control_player_win===",tostring_r(self.sort_side_cards_map))
    end

    player_result = self:get_control_player_result(self_table_type,control_uid)
    dbglog("===============22222control_player_win",player_result,sort)
end

--受控玩家作闲家时控制他输，依次使下注多的区域牌型变小
function MT_INDEX:control_player_lose(self_table_type,control_uid,side_sort_list)
    local player_result = self:get_control_player_result(self_table_type,control_uid)
    local sort = 1
    while player_result >= 0 and sort <= 4 do
        local card_list
        local side = side_sort_list[sort]
        local side_index = self:get_sort_index(side)                --某副牌是第几大
        local banker_index = self:get_sort_index(BANKER_SIDE_NUM)         
        if side_index < banker_index then      --天地玄黄比庄家牌型大，使天地玄黄牌型变小
            local cards_power = self:get_power_card_info(banker_index)
            card_list = nn_rule.get_cards(self.rest_cards,cards_power,nil,self.sorted_special_card_type)
        end
        if card_list and #card_list == 5 then
            -- local sort_list = copy_table(card_list)
            local sort_list = card_list
            nn_rule.sort_card_list(sort_list)
            self.side_cards_map[side] = card_list
            self.sort_side_cards_map[side] = sort_list
            self:update_rest_cards()        --更新剩余的牌
            player_result = self:get_control_player_result(self_table_type,control_uid)
            print("=============11111control_player_lose===",tostring_r(self.sort_side_cards_map))
        end
        sort = sort + 1
    end

    if player_result >= 0 then      --没有控制成功，则直接使庄家的牌与最大的牌交换
        local sort_map = self:get_sort_cards()    --五副牌由大到小的顺序
        local max_side = sort_map[1]
        if max_side ~= BANKER_SIDE_NUM then
            self.side_cards_map[max_side], self.side_cards_map[BANKER_SIDE_NUM] = self.side_cards_map[BANKER_SIDE_NUM], self.side_cards_map[max_side]
            self.sort_side_cards_map[max_side], self.sort_side_cards_map[BANKER_SIDE_NUM] = self.sort_side_cards_map[BANKER_SIDE_NUM], self.sort_side_cards_map[max_side]
        end
        print("=============22222control_player_lose===",tostring_r(self.sort_side_cards_map))
    end

    player_result = self:get_control_player_result(self_table_type,control_uid)
    dbglog("===============22222control_player_lose",player_result,sort)
end

--个人控制策略，调整控制玩家牌型
--1.受控玩家为庄家，控制他赢：contral_strategy_two（该函数控制庄家赢，策略见该函数说明）
--2.受控玩家为庄家，控制他输：contral_strategy_one（该函数控制庄家输，策略见该函数说明）
--3.受控玩家不是庄家，控制他赢：根据受控玩家下注区域额度由大到小依次使该区域牌型变大，直到玩家赢
--4.受控玩家不是庄家，控制他输：根据受控玩家下注区域额度由大到小依次使该区域牌型变小，直到玩家输
function MT_INDEX:adjust_control_player_cards(self_table_type,robot_type,control_uid,system_result,robots_manager)
    local control_win
    local player_result = self:get_control_player_result(self_table_type,control_uid)
    local banker_cards = self.sort_side_cards_map[BANKER_SIDE_NUM]
    local card_type = nn_rule.get_card_type(banker_cards, self.sorted_special_card_type)
    local robot_manager = false
    if system_result == constant.PERSONAL_STORE_WIN then
        control_win = true
    end
    dbglog("===========222222222222before result",player_result)
    if self.banker_uid == control_uid then   --控制方法同百人牛牛系统庄家控制(差别:受控玩家坐庄计算受控玩家相对于机器人和其他玩家的输赢)
        assert(player_result)
        if control_win then
            if player_result <= 0 then
                self:contral_strategy_two(control_win,card_type,robot_type,robot_manager,self_table_type,control_uid,robots_manager)
            end
        else
            if player_result >= 0 then
                self:contral_strategy_one(control_win,card_type,robot_type,robot_manager,self_table_type,control_uid)
            end
        end

    else      --根据受控玩家下注区域额度由大到小依次改变该区域牌型直到符合控制要求
        local side_sort_list = self:get_side_bet_sort(control_uid)
        if not player_result or not side_sort_list then     --受控玩家没有下注行为
            return
        end

        if control_win then
            if player_result <= 0 then
                self:control_player_win(self_table_type,control_uid,side_sort_list)
            end
        else
            if player_result >= 0 then
                self:control_player_lose(self_table_type,control_uid,side_sort_list)
            end
        end
    end
    player_result = self:get_control_player_result(self_table_type,control_uid)
    dbglog("===========222222222222after result",player_result)
end

-- function MT_INDEX:is_from_award_store()
--     return self.reduce_award_store
-- end

function MT_INDEX:init_side_result(side_result)
    for side = 1, MAX_SIDE_NUM - 1 do
        side_result[side] = { side = side, result_coins = 0}
    end
end

function MT_INDEX:init_player_result(uid, bet_result_list, pay_fee_map)
	--warlog("MT_INDEX:init_player_result", uid)

    local uid_bet_result = {}
    local side_result = {}
    local player_data = self.player_coins_data_map[uid]
    
    bet_result_list[uid] = uid_bet_result

    self:init_side_result(side_result)
    uid_bet_result.side_result = side_result
    uid_bet_result.result_coins = 0
    uid_bet_result.curr_coins = player_data.curr_own_coins
    uid_bet_result.uid = uid    
    pay_fee_map[uid] = 0

    if uid == self.banker_uid then
        uid_bet_result.is_banker = 1
    else
        uid_bet_result.is_banker = 0
    end
end

--获取每个区域机器人和玩家下注的金额
function MT_INDEX:get_all_bet(robot_manager)
    local bet_list = {}
    for side = 1, MAX_SIDE_NUM - 1 do
        bet_list[side] = {player_bet = 0, robot_bet = 0}
    end

    for uid, records in pairs(self.player_bet_map) do
        for side, r in pairs(records) do
            local bet_side = bet_list[side]
            if robot_manager[uid] ~= nil then
                bet_side.robot_bet = bet_side.robot_bet + r.bet_coins
            elseif self.banker_uid ~= uid then
                bet_side.player_bet = bet_side.player_bet + r.bet_coins
            end
        end
    end
    return bet_list
end

--玩家下注总额
function MT_INDEX:get_player_bet_total(robot_manager)
    local player_bet = 0
    local bet_list = self:get_all_bet(robot_manager)

    for side, bet_side in pairs(bet_list) do
        player_bet = player_bet + bet_side.player_bet
    end

    return player_bet
end

function MT_INDEX:judge_result(fee_percent,self_table_type)
    assert(self.game_status == GAME_STATUS_OVER)
    
    local bet_list = {}
    local bet_result_list = {}
    local tile_list = {}
    local sides_result_list = {}
    local pay_fee_map = {}   
    local need_reduce_map = {}
    local side_player_coins_map = {}
    local player_water = {}
    local str_date = os.date("%Y%m%d%H%M%S")
    self:init_player_result(self.banker_uid, bet_result_list, pay_fee_map)
    local banker_bet_result = bet_result_list[self.banker_uid]
    need_reduce_map[self.banker_uid] = 0
    
    --和庄家比较得出比较结果信息
    self:get_compare_info(tile_list, sides_result_list)
    print_r(sides_result_list)
    --根据比牌结果计算闲家和庄家的输赢(只有赢家需要扣除台费，输家不需要)
    for uid, records in pairs(self.player_bet_map) do
        self:init_player_result(uid, bet_result_list, pay_fee_map)
        need_reduce_map[uid] = 0
        local uid_bet_result = bet_result_list[uid]        
        for side, r in pairs(records) do
            local banker_side_result = banker_bet_result.side_result[side]
            local uid_side_result = uid_bet_result.side_result[side]
            local side_bet_result = sides_result_list[side]
            local times = side_bet_result.times
            local lost_coins = r.bet_coins * times
            bet_list[uid] = bet_list[uid] or 0
            bet_list[uid] = bet_list[uid] + r.bet_coins
            if side_bet_result.win then
                --闲家赢钱
                local win_coins = r.bet_coins * times

                uid_side_result.result_coins = win_coins
                uid_bet_result.result_coins = uid_bet_result.result_coins + win_coins
                need_reduce_map[uid] = need_reduce_map[uid] + r.bet_coins

                --庄家输钱
                banker_side_result.result_coins = banker_side_result.result_coins - lost_coins
                banker_bet_result.result_coins = banker_bet_result.result_coins - lost_coins

                player_water[uid] = player_water[uid] or 0
                player_water[uid] = player_water[uid] + r.bet_coins
            else
                --闲家输钱
                uid_side_result.result_coins = -lost_coins
                uid_bet_result.result_coins = uid_bet_result.result_coins - lost_coins

                --庄家赢钱
                local win_coins = 0
                local system_banker_pay_fee = 0
                if constant.SYSTEM_DO_BANKER_UID == self.banker_uid then
                    win_coins = r.bet_coins * times
                else
                    win_coins = r.bet_coins * times
                end

                banker_side_result.result_coins = banker_side_result.result_coins + win_coins                
                banker_bet_result.result_coins = banker_bet_result.result_coins + win_coins

                player_water[uid] = player_water[uid] or 0
                player_water[uid] = player_water[uid] + math_abs(lost_coins) 
            end

            if not side_player_coins_map[side] then
                 side_player_coins_map[side] = {}
            end
            table_insert(side_player_coins_map[side],{uid = uid,result_coins = uid_side_result.result_coins or 0})
        end

        if uid_bet_result.result_coins > 0 then
            local pay_fee = math_floor(uid_bet_result.result_coins * fee_percent)
            pay_fee_map[uid] = pay_fee
            uid_bet_result.result_coins = uid_bet_result.result_coins - pay_fee
        end
    end

    if not self.is_robot_banker and banker_bet_result.result_coins < 0 then
        player_water[self.banker_uid] = player_water[self.banker_uid] or 0
        player_water[self.banker_uid] = player_water[self.banker_uid] + math_abs(banker_bet_result.result_coins)    
    end

    if banker_bet_result.result_coins > 0 then
        local banker_fee = math_floor(banker_bet_result.result_coins * fee_percent)
        pay_fee_map[self.banker_uid] = banker_fee
        banker_bet_result.result_coins = banker_bet_result.result_coins - banker_fee
    end
    
    --self.game_status = GAME_STATUS_OVER
    self.game_result.bet_list = bet_list    
    self.game_result.bet_result_list = bet_result_list
    self.game_result.sides_result_list = sides_result_list
    self.game_result.tile_list = tile_list
    self.game_result.pay_fee_map = pay_fee_map
    self.game_result.need_reduce_map = need_reduce_map
    self.game_result.side_player_coins_map = side_player_coins_map
    self.game_result.player_water = player_water

    return true
end

function MT_INDEX:robot_can_use_pic(pic_conf)
    if not pic_conf or not pic_conf.select_pic then 
        return 
    end
    if self.robot_use_pic_num >= 2 then --单局最多允许2个机器人使用表情
        return
    end
    local use_rate = pic_conf.use_rate or 0
    local use_pic = pic_conf.select_pic 
    if math_random(1,100) <= pic_conf.use_rate then
        local select_pic = use_pic[math_random(1,#use_pic)]
        local delay_time
        if pic_conf.delay_time then
            delay_time = math_random(pic_conf.delay_time[1],pic_conf.delay_time[2])
        end
        return select_pic,delay_time
    end

    return false
end

function MT_INDEX:add_use_pic_num()
    self.robot_use_pic_num = self.robot_use_pic_num + 1
end

function MT_INDEX:get_game_result()
    assert(self.game_status == GAME_STATUS_OVER)

    return self.game_result
end

function MT_INDEX:get_banker_uid()
    return self.banker_uid
end

function M.new()
    local o = {}
    return setmetatable(o, { __index = MT_INDEX })
end



return M
